package com.hqq.search.bst;

import java.util.LinkedList;
import java.util.Queue;

/**
 * BST
 * 二叉查找树
 * Created by heqianqian on 2017/8/5.
 */
public class BST<K extends Comparable<K>, V> {

    public Node root;

    public BST() {
        //this.root = new Node(null,null,0);
    }

    class Node {
        private K key;
        private V value;
        private Node left, right;
        private int size;

        public Node() {
        }

        public Node(K key, V value, int size) {
            this.key = key;
            this.value = value;
            this.size = size;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "key=" + key +
                    ", value=" + value +
                    '}';
        }
    }

    public int size() {
        return this.size(root);
    }

    public int size(Node x) {
        if (x == null) {
            return 0;
        }
        return x.size;
    }

    public V get(K key) {
        return get(root, key);
    }

    /**
     * 在x为根节点的子树中查找并返回key所对应的值
     */
    private V get(Node node, K key) {
        if (node == null) {
            return null;
        }
        int cmp = key.compareTo(node.key);
        if (cmp < 0) {
            return get(node.left, key);
        } else if (cmp > 0) {
            return get(node.right, key);
        } else {
            return node.value;
        }
    }

    public void put(K key, V value) {
        root = put(root, key, value);
    }

    private Node put(Node node, K key, V value) {
        if (node == null) {//如果树的空的 就返回一个新的节点作为树的根节点
            return new Node(key, value, 1);
        }
        int cmp = key.compareTo(node.key);
        if (cmp < 0) {
            node.left = put(node.left, key, value);
        } else if (cmp > 0) {
            node.right = put(node.right, key, value);
        } else {
            node.value = value;
        }
        node.size = size(node.left) + size(node.right);
        return node;
    }

    public K min() {
        return min(root).key;
    }

    private Node min(Node node) {
        if (node.left == null) {
            return node;
        }
        return min(node.left);
    }

    public K max() {
        return max(root).key;
    }

    public Node max(Node node) {
        if (node.right == null) {
            return node;
        }
        return max(node.right);
    }

    public K floor(K key) {
        Node node = floor(root, key);
        if (node == null) {
            return null;
        }
        return node.key;
    }

    private Node floor(Node node, K key) {
        if (node == null) {
            return null;
        }
        int cmp = key.compareTo(node.key);
        if (cmp == 0) {
            return node;
        } else if (cmp < 0) {
            return floor(node.left, key);
        }
        Node t = floor(node.right, key);
        if (t != null) {
            return t;
        } else {
            return node;
        }
    }

    public K select(int k) {
        return select(root, k).key;
    }

    public Node select(Node node, int k) {
        //返回排名为k的节点
        if (node == null) {
            return null;
        }
        int t = size(node.left);
        if (t > k) {
            return select(node.left, k);
        } else if (t < k) {
            return select(node.right, k);
        } else {
            return node;
        }
    }

    /**
     * 返回给定键的排名
     */
    public int rank(K key) {
        return rank(key, root);
    }

    public int rank(K key, Node node) {
        if (node == null) {
            return 0;
        }
        int cmp = key.compareTo(node.key);
        if (cmp < 0) {
            return rank(key, node.left);
        } else if (cmp > 0) {
            return 1 + size(node.left) + size(node.right);
        } else {
            return size(node.left);
        }
    }

    public void deleteMin() {
        root = deleteMin(root);
    }

    private Node deleteMin(Node node) {
        if (node.left == null) {
            return node.right;
        }
        node.left = deleteMin(node.left);
        node.size = size(node.left) + size(node.right) + 1;
        return node;
    }

    public void delete(K key) {
        root = delete(root, key);
    }

    private Node delete(Node node, K key) {
        if (node == null) {
            return null;
        }
        int cmp = key.compareTo(node.key);
        if (cmp < 0) {
            node.left = delete(node.left, key);
        } else if (cmp > 0) {
            node.right = delete(node.right, key);
        } else {
            if (node.right == null) {
                return node.left;
            }
            if (node.left == null) {
                return node.right;
            }
            Node n = node;
            node = min(n.right);
            node.right = deleteMin(n.right);
            node.left = n.left;
        }
        node.size = size(node.left) + size(node.right) + 1;
        return node;
    }

    public void print(Node node) {
        if (node == null) {
            return;
        }
        print(node.left);
        System.out.println(node.value);
        print(node.right);
    }

    /**
     * 范围查找操作
     */
    public Iterable<K> keys() {
        return keys(min(), max());
    }

    public Iterable<K> keys(K low, K high) {
        Queue<K> queue = new LinkedList<>();
        keys(root, queue, low, high);
        return queue;
    }

    private void keys(Node node, Queue<K> queue, K low, K high) {
        if (node == null) {
            return;
        }
        int cmpLow = low.compareTo(node.key);
        int cmpHigh = high.compareTo(node.key);
        if (cmpLow < 0) {
            keys(node.left, queue, low, high);
        }
        if (cmpLow <= 0 && cmpHigh >= 0) {
            queue.add(node.key);
        }
        if (cmpHigh > 0) {
            keys(node.right, queue, low, high);
        }
    }
}
